package main

import (
	"fmt"
)

type Base1 struct {
	name1 string
}

func (base1 *Base1) show() {
	fmt.Println(base1.name1)
}

type Base2 struct {
	name2 string
}

func (base2 *Base2) show() {
	fmt.Println(base2.name2)
}

func (base2 *Base2) show2() {
	fmt.Println("show2", base2.name2)
}

//anonymous struce embeding can be implemented through both value and pointer
//such as Base1 or *Base1. To use the embeded attributes or method directly from outside,
//the two embeding manners make no differences. The key differences of the two embeding manners ar:
//1. the instance data struture: Using Base1, the Base1 instance data instructure is composited into Child instance. Using *Base1, the pointer of Base1 instance is composited in to Child instance.
//2. Initializtion parameters must correspond to the real data structure of the embeded. Namely use Base1 instance to initialze Base1 embeding and use Base1 instance pointer to initialize *Base1 embeding.
//3. Base1 embeding only gives Base1's methods with value receiver to the methods collection of Child. But *Base1 embeding gives Base1's methods with value receiver and pointer receiver to the methods collection of Child. See interface.md to get the details.
type Child struct {
	Base1   //anonymous struct embedding
	base2 Base2
	name  string
}

func main() {
	// c := Child{}
	var c Child
	c.name1 = "name1"   //only attributes of anonymous embeded struct are hoisted to outer
	fmt.Println(c.name1)
	fmt.Println(c.Base1.name1)  //attributes of anonymous embeded struct can also be accessed from embeded struct name
	c.show()
    c.Base1.show()

	// fmt.Println(c.name2) //attributes of non-anonymous embeded struct are NOT hoisted to outer
    c.base2.name2 = "name2" //attributes of non-anonymous embeded struct can be accessed from its embeded attribute name
	fmt.Println(c.base2.name2)
	c.show()
    // c.show2()
    c.base2.show()
    c.base2.show2()

	fmt.Println(c.name)
}
